import { Computed, Mut, VueService } from "vue3-oop";
import { WidgetNode, WidgetItem, ReserveItem } from './index'
import { nanoid } from "nanoid";
import { newATTR,LAYOUT,GRID,CARD } from '../widgets/attr-widget'

export default class FormData extends VueService {
  // 表单大小 暂时用不到
  @Mut() formSize = 'mini';
  // 浏览器窗口大小
  @Mut() winSize = 'xs' as 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | 'xxxl';
  // 默认标签宽度
  @Mut() labelWidth = 100;
  // 默认标签对齐方向
  @Mut() labelAlign = 'left' as 'left' | 'right';
  // key是widgetId，value是WidgetNode
  @Mut() nodeMap = new Map<string, WidgetNode>();
  // WidgetNode的树形结构
  @Mut() nodeTree = {} as WidgetNode;
  // 选中的组件widgetId
  @Mut() private selectedWidgetId = '';

  constructor() {
    super();
    this.init();
  }

  /**
   * 初始化
   */
  init = (): void => {
    const rootWidgetItem = {
      widgetId: 'ROOT', type: 'GRID', label:'栅格',
      GRID:{
        defaultSpan: 12,
        align: 'top',
        justify: 'start',
        wrap: true,
        labelWidth: 100,
        labelAlign: 'left',
        gutter: [
          { xs: 0, sm: 0, md: 0, lg: 0, xl: 0, xxl: 0, xxxl: 0 },
          { xs: 0, sm: 0, md: 0, lg: 0, xl: 0, xxl: 0, xxxl: 0 }
        ],
        layout_status: '1',
        layout_reactive: { 
          xs: { span: 12, pull: 0, push: 0, offset: 0, order: 0 }, 
          sm: { span: 12, pull: 0, push: 0, offset: 0, order: 0 }, 
          md: { span: 12, pull: 0, push: 0, offset: 0, order: 0 }, 
          lg: { span: 12, pull: 0, push: 0, offset: 0, order: 0 }, 
          xl: { span: 12, pull: 0, push: 0, offset: 0, order: 0 }, 
          xxl: { span: 12, pull: 0, push: 0, offset: 0, order: 0 }, 
          xxxl: { span: 12, pull: 0, push: 0, offset: 0, order: 0 } 
        }
      }
    } as WidgetItem;
    const rootWidgetNode = new WidgetNode(
      this, undefined, 'ROOT', 'GRID', rootWidgetItem
    );
    this.nodeMap.set(rootWidgetItem.widgetId, rootWidgetNode);
    this.nodeTree = rootWidgetNode;
  }

  /**
   * 清除根节点外的其他所有子孙节点
   */
  clear =():void=>{
    const rootWidgetNode = this.nodeMap.get('ROOT') as WidgetNode;
    this.nodeMap.clear();
    this.nodeMap.set(rootWidgetNode.widgetId, rootWidgetNode);
    this.nodeTree.children = []
  }

  /**
   * 计算窗口尺寸
   */
  loadWinSize = (): void => {
    const winWidth = window.document.body.clientWidth
    let winSize = 'xs'
    winSize = winWidth >= 576 ? 'sm' : winSize;
    winSize = winWidth >= 768 ? 'md' : winSize;
    winSize = winWidth >= 992 ? 'lg' : winSize;
    winSize = winWidth >= 1200 ? 'xl' : winSize;
    winSize = winWidth >= 1600 ? 'xxl' : winSize;
    winSize = winWidth >= 2000 ? 'xxxl' : winSize;
    this.winSize = winSize as any;
  }

  /**
   * 选中的组件ITEM
   */
  @Computed() get selectedWidgetItem(){
    return this.nodeMap.get(this.selectedWidgetId)?.widgetItem
  }

  /**
   * 输入型组件的字段编码和WidgetItem的MAP
   */
  @Computed() get codeItemMap(){
    const codeItemMap = new Map<string,WidgetItem>();
    this.nodeMap.forEach((wigetNode:WidgetNode)=>{
      const { widgetItem } = wigetNode;
      const attr = (widgetItem as any)[widgetItem.type];
      if(attr.field_code){
        codeItemMap.set(attr.field_code,widgetItem);
      }
    });
    return codeItemMap;
  }

  /**
   * 输入型组件的字段编码和值的Object
   */
  @Computed() get codeValueObj(){
    const codeValueObj = {} as any;
    this.nodeMap.forEach((wigetNode:WidgetNode)=>{
      const { widgetItem } = wigetNode;
      if(widgetItem.setValue instanceof Function){
        widgetItem.setValue();
      }
      const attr = (widgetItem as any)[widgetItem.type];
      if(attr.field_code){
        codeValueObj[attr.field_code] = {
          type: widgetItem.type,
          code: attr.field_code,
          label: attr.field_label,
          value: attr.field_value,
          format: attr.field_format
        };
      }
    });
    return codeValueObj;
  }

  @Computed() get formModel(){
    const formModel = {} as any;
    this.nodeMap.forEach((wigetNode:WidgetNode)=>{
      const { widgetItem } = wigetNode;
      const attr = (widgetItem as any)[widgetItem.type];
      if(attr.field_code){
        formModel[attr.field_code] = attr.field_value;
      }
    });
    return formModel;
  }

  /**
   * 设置选中组件的ID
   * @param widgetId 选中的ID 
   */
  setSelectedWidgetId=(widgetId:string)=>{
    // 将点击项的id赋值给 selectedWidgetId 用于判定是否选中
    if(widgetId&&widgetId!=='ROOT'){// 最最外层的草稿 GRID 无法选中
      this.selectedWidgetId = widgetId;
    }
  }

  /**
   * 判断是否是选中组件的ID
   * @param widgetId 判断的ID
   */
  isSelectedWidgetId=(widgetId:string):boolean=>{
    return this.selectedWidgetId===widgetId
  }

  /**
   * 获取FormData的JSON表达数据
   */
  getJsonData=():Object=>{
    const { formSize, winSize, labelWidth, labelAlign } = this;
    const nodeTreeToJson=(widgetNode:WidgetNode):Object=>{
      const { parentId, widgetId, type } = widgetNode;
      const widgetItem = JSON.parse(JSON.stringify(widgetNode.widgetItem))
      const children = widgetNode.children.map((childNode)=>nodeTreeToJson(childNode));
      return { parentId, widgetId, type, widgetItem, children }
    }
    const nodeTree = nodeTreeToJson(this.nodeTree);
    return { formSize, winSize, labelWidth, labelAlign, nodeTree }
  }

  /**
   * 从JSON数据加载FormData
   * @param jsonData 从方法 getJsonData 获取的JSON数据
   */
  loadFromJsonData=(jsonData:any):void=>{
    this.clear();
    this.formSize = jsonData.formSize;
    this.winSize = jsonData.winSize;
    this.labelWidth = jsonData.labelWidth;
    this.labelAlign = jsonData.labelAlign;
    const jsonToNodeTree=(jsonTree:any)=>{
      const { parentId, widgetId, type } = jsonTree;
      const widgetItem = jsonTree.widgetItem as WidgetItem;
      const children = jsonTree.children.map((childNode:any)=>jsonToNodeTree(childNode)) as WidgetNode[];
      const widgetNode = new WidgetNode(this,parentId,widgetId,type,widgetItem);
      widgetNode.children = children;
      this.nodeMap.set(widgetId,widgetNode);
      return widgetNode;
    }
    this.nodeTree = jsonToNodeTree(jsonData.nodeTree);
  }
  
  /**
   * 新增组件节点
   * @param parentNode 父节点NODE
   * @param reserveItem 待添加组件的简略信息
   */
  createNewWidgetNode=(parentNode:WidgetNode,reserveItem:ReserveItem,index:number)=>{
    const parentItem = parentNode.widgetItem;

    const newWidgetItem = {
      widgetId: reserveItem.type+'_'+nanoid(),
      type: reserveItem.type,
      label: reserveItem.label,
    } as WidgetItem;
    newATTR(parentItem,newWidgetItem);

    const newWidgetNode = new WidgetNode(
      this,
      parentNode.widgetId,
      newWidgetItem.widgetId,
      newWidgetItem.type,
      newWidgetItem
    );

    if(newWidgetNode.type==='CARD'){
      const attr = newWidgetItem.CARD as CARD;
      attr.tabList.push({key:'tab1',tab:'分页1'});
      
      const newCardItem = {
        widgetId: 'GRID_'+nanoid(),
        type: 'GRID',
        label: '栅格',
      } as WidgetItem;
      newATTR(newWidgetItem,newCardItem);
      
      const newCardNode = new WidgetNode(
        this,
        newWidgetNode.widgetId,
        newCardItem.widgetId,
        newCardItem.type,
        newCardItem
      );
      newWidgetNode.children.push(newCardNode);
      this.nodeMap.set(newCardNode.widgetId,newCardNode);
    }

    parentNode.children[index] = newWidgetNode;
    this.nodeMap.set(newWidgetNode.widgetId,newWidgetNode);
    this.setSelectedWidgetId(newWidgetNode.widgetId);
  }

}